<?php

require_once 'HTTP/OAuth.php';
require_once 'HTTP/OAuth/Consumer.php';
require_once 'HTTP/OAuth/Consumer/Request.php';

require_once dirname(__FILE__) . '/SimpleMethod.php';

/**
 * OAuth settings for application can be taken on the page
 * [http://annonsera.se/usr/apps/list.html]
 */
class GG_API_OauthMethod extends GG_API_SimpleMethod {

	/**
	 * Array of OAuth param names that need to be escaped if used in API.
	 * E.g. "callback" will be escaped to "gg_callback".
	 */
	private static $paramNamesToEscape = array(
		'consumer_key',
		'token',
		'token_secret',
		'signature_method',
		'signature',
		'timestamp',
		'nonce',
		'verifier',
		'version',
		'callback'
	);

	/**
	 * @var string Your application consumer key.
	 */
	protected $oauthConsumerKey = null;

	/**
	 * @var string Your application consumer secret.
	 */
	protected $oauthConsumerSecret = null;

	/**
	 * @var string Access token.
	 */
	protected $oauthToken = null;

	/**
	 * @var string Access token secret.
	 */
	protected $oauthTokenSecret = null;

	/**
	 * @var bool true if method must use OAuth.
	 */
	protected $useOauth = true;

	public function __construct($configArray = null) {
		parent::__construct($configArray);
	}

	protected function getParamNamesToEscape() {
		$result = parent::getParamNamesToEscape();
		if ($this->isUseOauth()) {
			$result = array_merge($result, self::$paramNamesToEscape);
		}
		return $result;
	}

	public function setUseOauth($use) {
		if (!is_bool($use)) {
			$use = false;
		}
		$this->useOauth = $use;
	}

	public function isUseOauth() {
		return $this->useOauth;
	}

	public function setOauthConsumerKey($consumerKey) {
		$this->oauthConsumerKey = $consumerKey;
	}

	public function getOauthConsumerKey() {
		$result = $this->oauthConsumerKey;
		if ($result === null) {
			$result = $this->getConfigValue('oauthConsumerKey');
		}
		return $result;
	}

	public function hasOauthConsumerKey() {
		return !self::isStringEmpty($this->getOauthConsumerKey());
	}

	public function setOauthConsumerSecret($consumerSecret) {
		$this->oauthConsumerSecret = $consumerSecret;
	}

	public function getOauthConsumerSecret() {
		$result = $this->oauthConsumerSecret;
		if ($result === null) {
			$result = $this->getConfigValue('oauthConsumerSecret');
		}
		return $result;
	}

	public function hasOauthConsumerSecret() {
		return !self::isStringEmpty($this->getOauthConsumerSecret());
	}

	public function setOauthToken($token) {
		$this->oauthToken = $token;
	}

	public function getOauthToken() {
		$oauthToken = $this->oauthToken;
		if ($oauthToken === null) {
			$oauthToken = $this->getStore()->getOauthToken();
		}
		return $oauthToken;
	}

	public function hasOauthToken() {
		return !self::isStringEmpty($this->getOauthToken());
	}

	public function setOauthTokenSecret($tokenSecret) {
		$this->oauthTokenSecret = $tokenSecret;
	}

	public function getOauthTokenSecret() {
		$oauthTokenSecret = $this->oauthTokenSecret;
		if ($oauthTokenSecret === null) {
			$oauthTokenSecret = $this->getStore()->getOauthTokenSecret();
		}
		return $oauthTokenSecret;
	}

	public function hasOauthTokenSecret() {
		return !self::isStringEmpty($this->getOauthTokenSecret());
	}

	/**
	 * @return HTTP_OAuth_Consumer New instance.
	 */
	protected function newOauthConsumer() {
		$this->validateOauthConfig();

		$httpRequest = new HTTP_Request2();
		$httpRequest->setHeader('Accept-Encoding', '.*');
		$request = new HTTP_OAuth_Consumer_Request;
		$request->accept($httpRequest);

		$consumer = new HTTP_OAuth_Consumer(
			$this->getOauthConsumerKey(),
			$this->getOauthConsumerSecret(),
			$this->getOauthToken(),
			$this->getOauthTokenSecret()
		);

		$consumer->accept($request);

		return $consumer;
	}

	/**
	 * Throws GG_API_Exception if one of method params/settings is invalid.
	 */
	public function validate() {
		parent::validate();
		if ($this->isUseOauth()) {
			$this->validateOauthConfig();
		}
	}

	/**
	 * @throws GG_API_Exception if missed one of required OAuth params:
	 * consumer key, consumer secret, token, token secret.
	 */
	protected function validateOauthConfig() {
		if (!$this->hasOauthConsumerKey()) {
			throw new GG_API_Exception("OAuth consumer key is missed.");
		}
		if (!$this->hasOauthConsumerSecret()) {
			throw new GG_API_Exception("OAuth consumer secret is missed.");
		}
		if (!$this->hasOauthToken()) {
			throw new GG_API_Exception("OAuth token is missed.");
		}
		if (!$this->hasOauthTokenSecret()) {
			throw new GG_API_Exception("OAuth token secret is missed.");
		}
	}

	/**
	 * @return GG_API_Response Object that represents method response.
	 * 
	 * @throws GG_API_Exception if OAuth used and missed one of required
	 * OAuth params: consumer key, consumer secret, token, token secret.
	 */
	public function call() {
		$this->validate();
		if ($this->isUseOauth()) {
			$consumer = $this->newOauthConsumer();
			$httpResponse = $consumer->sendRequest($this->getUrl(),
					$this->getPreparedParams(), $this->getHttpMethod());
			return $this->prepareResponse($httpResponse);
		} else {
			return parent::call();
		}
	}
}

?> 